home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / overview / dave falkenburg's sprocket / lib / dialogwindow.cp < prev    next >
Encoding:
Text File  |  2000-09-28  |  6.8 KB  |  237 lines

  1. /*
  2.     File:        DialogWindow.cp
  3.  
  4.     Contains:    Implementation of a base class for Modeless Dialogs
  5.  
  6.     Written by: Dave Falkenburg    
  7.  
  8.     Copyright:    Copyright © 1993-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 8/19/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 11/16/94    DRF                Added explicit #include <Traps.h> for latest universal headers.
  21.                 11/12/94    DRF                Fix a bug in EventFilter method which returned false even if a
  22.                                             dialog item was hit.
  23.                 11/8/94        DRF                We have better menu handling methods, so use them instead of the
  24.                                             old “DoEditMenu” method.
  25.                 10/17/94    DRF                 ItemHit is now a pure-virtual method. Fixed bugs in DoEditMenu.
  26.                                              Call StdFilterProc inside EventFilter to handle ok, cancel,
  27.                                             and I-beam cursor tracking.
  28.                 9/27/94        DRF                 AppLib.h is now Sprocket.h
  29.                 9/9/94        DRF                Reordered headers and removed redundant #includes. Also fixed
  30.                                             constants in DoEditMenu.
  31.  
  32. */
  33. #include "Sprocket.h"
  34. #include "DialogWindow.h"
  35. #include "StandardMenus.h"
  36. #include <Traps.h>
  37.  
  38. TDialogWindow::TDialogWindow(DialogTemplateID dialogTemplateID)
  39.     {
  40.     fTemplateID = dialogTemplateID;
  41.     this->CreateWindow(kNormalWindow);
  42.     }
  43.  
  44.  
  45. WindowPtr
  46. TDialogWindow::MakeNewWindow(WindowPtr behindWindow)
  47.     {
  48.     return GetNewDialog(fTemplateID,nil,behindWindow);
  49.     }
  50.  
  51.  
  52. ////////////////////////////////////////////////////////////////////////////////////
  53. //
  54. //    EventFilter strategy for Dialog Window
  55. //
  56. //    Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
  57. //    and DialogSelect, only do these things when a Modless Dialog is the frontmost
  58. //    window. (e.g., it’s event filter is active)
  59. //
  60. //    NOTE: We always pass events through, except when an item has been hit.
  61. //
  62. //    You may be thinking that it is easier to just rewrite the Dialog Manager in
  63. //    this program. You’re probably right.
  64.  
  65. pascal    WindowPtr    FrontWindowPatchForDialogs();
  66.  
  67.  
  68. pascal    WindowPtr
  69. FrontWindowPatchForDialogs()
  70.     {
  71.     return MyFrontNonFloatingWindow();
  72.     }
  73.  
  74. #define    uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowPtr))))
  75.  
  76. UniversalProcPtr FrontWindowPatchUPP
  77. = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
  78.  
  79.  
  80. Boolean
  81. TDialogWindow::EventFilter(EventRecord *theEvent)
  82.     {
  83.     GrafPtr                oldPort;
  84.     UniversalProcPtr    oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
  85.     DialogPtr            aDialog;
  86.     Boolean                eventHasBeenGobbled = false;
  87.     short                aDialogItem;
  88.     short                oldWindowKind;
  89.     
  90.     //    Don’t snarf keypresses meant for menus
  91.     if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
  92.         return false;
  93.  
  94.     GetPort(&oldPort);
  95.     SetPort(fWindow);
  96.     
  97.     //    Patch in our version of FrontWindow so that IsDialogEvent will do the right
  98.     //    thing. DialogManager should check both frontmost floating and frontmost
  99.     //    non-floating windows, however we don’t support floating dialogs.
  100.     SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
  101.  
  102.     //    Jam the windowKind of our dialog window back to dialogKind so that the
  103.     //    Dialog Manager can recognize our window as a dialog window.
  104.     oldWindowKind = ((WindowPeek) fWindow)->windowKind;
  105.     ((WindowPeek) fWindow)->windowKind = dialogKind;
  106.     
  107.     
  108.     if (IsDialogEvent(theEvent))
  109.         {
  110.         //    It’s definitely a dialog event, so let the DialogMgr figure things out.
  111.         //
  112.         //    We first let StdFilterProc have a crack at it so that the default
  113.         //    and cancel buttons are properly processed (as well as automagic text
  114.         //    cursor tracking).
  115.         
  116.         //    If StdFilterProc didn’t find anything to do, go ahead and call
  117.         //    DialogSelect to figure out if the user did anything important.
  118.  
  119.         //    Isn’t this alot easier than what Inside Mac says to do?
  120.  
  121.         eventHasBeenGobbled = StdFilterProc(fWindow,theEvent,&aDialogItem);
  122.         if (eventHasBeenGobbled == false)
  123.             eventHasBeenGobbled = DialogSelect(theEvent,&aDialog,&aDialogItem);
  124.         }
  125.  
  126.     //    Restore the windowKind
  127.     ((WindowPeek) fWindow)->windowKind = oldWindowKind;
  128.  
  129.     //    Put FrontWindow back the way it really belongs
  130.     SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
  131.  
  132.     if (eventHasBeenGobbled)
  133.         {
  134.         this->ItemHit(aDialogItem);    //    Call user’s method to deal with a hit
  135.         eventHasBeenGobbled = true;
  136.         }
  137.         
  138.     SetPort(oldPort);
  139.     
  140.     return eventHasBeenGobbled;
  141.     }
  142.  
  143.  
  144. void
  145. TDialogWindow::Activate(Boolean activating)
  146.     {
  147.     EventRecord            fakeEvent;
  148.  
  149.     /*    (De)activates are NOT automagically handled because our floating
  150.      *    windows prevent real activate events from ever being generated
  151.      *    for any non-floaters windows.
  152.      *
  153.      *    Our strategy is to fool the dialog manager into thinking that
  154.      *    things are still fine by passing it a fake (de)activate event.
  155.      *
  156.      *    Luckily, we don’t have to patch FrontWindow to make DialogSelect
  157.      *    work for activate and update events.
  158.      */
  159.         
  160.     OSEventAvail(0,&fakeEvent);        //    Get an intialized, but otherwise empty event record
  161.     
  162.     fakeEvent.what = activateEvt;
  163.     fakeEvent.message = (unsigned long) fWindow;
  164.     if (activating)
  165.         fakeEvent.modifiers |= activeFlag;
  166.     else
  167.         fakeEvent.modifiers &= ~activeFlag;
  168.  
  169.     //    Pass event on to DialogSelect
  170.     
  171.     DialogPtr    aDialog;
  172.     short        aDialogItem;
  173.     
  174.     (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
  175.     }
  176.     
  177.  
  178. void
  179. TDialogWindow::Draw(void)
  180.     {
  181.     //    Automagically handled by Dialog Manager when we are
  182.     //    the frontmost window, but not at other times because
  183.     //    we only set the windowKind to dialogKind inside our
  184.     //    EventFilter (which is only active when we are frontmost).
  185.     
  186.     UpdateDialog((DialogPtr) fWindow, fWindow->visRgn);
  187.     }
  188.     
  189.     
  190. void
  191. TDialogWindow::Click(EventRecord * /* anEvent */)
  192.     {
  193.     /*    The only time this method is called is to handle a click
  194.      *    when the dialog window isn’t frontmost. All other times,
  195.      *    DialogSelect will do everything for us.
  196.      *
  197.      *    If our dialog contains useritems with the ability to
  198.      *    be the source of a drag we’d need to start drag tracking
  199.      *    in here.
  200.      */
  201.      
  202.     this->Select();
  203.     }
  204.  
  205.     
  206. void
  207. TDialogWindow::DoMenuSelection(short menu, short item)
  208.     {
  209.     if (menu == mEdit)
  210.         {
  211.         switch (item)
  212.             {
  213.             case    iUndo:
  214.                 break;
  215.                 
  216.             case    iCut:
  217.                 DialogCut(fWindow);
  218.                 return;
  219.                 
  220.             case    iCopy:
  221.                 DialogCopy(fWindow); 
  222.                 return;
  223.                 
  224.             case    iPaste:
  225.                 DialogPaste(fWindow); 
  226.                 return;
  227.                 
  228.             case    iClear:
  229.                 DialogDelete(fWindow); 
  230.                 return;
  231.             }
  232.         }
  233.     
  234.     //    Call through to inherited method
  235.     TWindow::DoMenuSelection(menu,item);
  236.     }
  237.